package com.colter.project.sample.thread.part05.test1;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit;

//Fork Join Pool
public class Test2 {
	public static void main(String[] args) {
		ProductListGenerator generator = new ProductListGenerator();
		List<Product> products = generator.generate(10000);
		Task2 task = new Task2(products, 0, products.size(), 0.20);
		ForkJoinPool pool = new ForkJoinPool();
		pool.execute(task);
		do {
			System.out.println("Main:Thread Count:" + pool.getActiveThreadCount());
			System.out.println("Main:Thread Steal:" + pool.getStealCount());
			System.out.println("Main: Parallelism:" + pool.getParallelism());
			try {
				TimeUnit.MICROSECONDS.sleep(5);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (!task.isDone());

		pool.shutdown();
		if (task.isCompletedNormally()) {
			System.out.println("Main: The process has completed normally.");
		}

		for (int i = 0; i < products.size(); i++) {
			Product p = products.get(i);
			if (p.getPrice() != 12) {
				System.out.println(p);
			}

		}
		System.out.println("Main: End program.");
	}
}

class Product {
	private String name;
	private double price;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Product [name=" + name + ", price=" + price + "]";
	}

}

class ProductListGenerator {
	public List<Product> generate(int size) {
		List<Product> ret = new ArrayList<>();
		for (int i = 0; i < size; i++) {
			Product product = new Product();
			product.setName("Product" + i);
			product.setPrice(10);
			ret.add(product);
		}
		return ret;
	}
}

class Task2 extends RecursiveAction {

	private static final long serialVersionUID = 1L;

	private List<Product> products;

	private int first;
	private int last;
	private double increment;

	public Task2(List<Product> products, int first, int last, double increment) {
		super();
		this.products = products;
		this.first = first;
		this.last = last;
		this.increment = increment;
	}

	@Override
	protected void compute() {
		if (last - first < 10) {
			updatePrices();
		} else {
			int middle = (last + first) / 2;
			System.out.println("Task: Pending Tasks:" + getQueuedTaskCount());
			Task2 t1 = new Task2(products, first, middle + 1, increment);
			Task2 t2 = new Task2(products, middle + 1, last, increment);
			invokeAll(t1, t2);
		}
	}

	private void updatePrices() {
		for (int i = first; i < last; i++) {
			Product product = products.get(i);
			product.setPrice(product.getPrice() * (1 + increment));
		}
	}

}
